/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#define CHPASS_INTERNAL_ACCESS
#include "common/setup_before.h"
#include "channel_password.h"

#include <cstdio>

#include "compat/strcasecmp.h"
#include "common/list.h"
#include "common/eventlog.h"
#include "common/xalloc.h"
#include "common/field_sizes.h"

#include "prefs.h"
#include "common/setup_after.h"

namespace pvpgn
{

namespace bnetd
{

static t_list * chpasslist_head=NULL;

t_chpass * get_chpass(char const * channel_name)
{
  t_elem  * curr;
  t_chpass * chpass;

  if (chpasslist_head)
  {
    LIST_TRAVERSE(chpasslist_head,curr)
    {
      if (!(chpass = (t_chpass*)elem_get_data(curr)))
      {
        eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list");
        continue;
      }
      if (strcasecmp(channel_name,chpass->channel_name)==0) return chpass;
    }
  }
  return NULL;
}

char * channel_get_chpass(char const * channel_name)
{
  t_chpass * chpass;

  if (!(chpass = get_chpass(channel_name)))
    return NULL;
  else
    return chpass->chpass;
}

int chpasslist_save(char const * chpass_file)
{
  t_elem  * curr;
  t_chpass * chpass;
  std::FILE * fp;

  if (chpasslist_head)
  {

    if ((fp = std::fopen(chpass_file,"w"))==NULL)
    {
      eventlog(eventlog_level_error, __FUNCTION__,"can't open chpass file");
      return -1;
    }

    LIST_TRAVERSE(chpasslist_head,curr)
    {
      if (!(chpass = (t_chpass*)elem_get_data(curr)))
      {
        eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list");
        continue;
      }
      if (chpass->save == DO_SAVE_CHPASS)
        std::fprintf(fp,"\"%s\",\"%s\"\n",chpass->channel_name,chpass->chpass);
    }

    std::fclose(fp);
  }

  return 0;
}

int chpasslist_add_chpass(char const * channel_name, char const * chpass_text, int do_save)
{
  t_chpass * chpass;

  chpass = (t_chpass*)xmalloc(sizeof(t_chpass));
  chpass->channel_name = xstrdup(channel_name);
  chpass->chpass = xstrdup(chpass_text);
  list_prepend_data(chpasslist_head,chpass);
  chpass->save = do_save;
  return 0;
}

int channel_set_chpass(char const * channel_name, char const * chpass_text, int do_save)
{
  t_chpass * chpass;

  if (!(channel_name))
  {
    eventlog(eventlog_level_error,__FUNCTION__,"got NULL channel_name");
    return -1;
  }

  if (!(chpass_text))
  {
    eventlog(eventlog_level_error,__FUNCTION__,"got NULL chpass");
    return -1;
  }

  if ((chpass = get_chpass(channel_name)))
  {
    xfree((void *)chpass->chpass);
    chpass->chpass = xstrdup(chpass_text);
  }
  else
  {
    chpasslist_add_chpass(channel_name, chpass_text,do_save);
  }

  if (do_save == DO_SAVE_CHPASS)
  {
    if (chpasslist_save(prefs_get_chpassfile())<0)
    {
      eventlog(eventlog_level_error,__FUNCTION__,"error saving chpass list");
      return -1;
    }
  }

  return 0;
}

int chpasslist_load(char const * chpassfile)
{
  std::FILE * fp;
  char channel_name[MAX_CHANNELNAME_LEN];
  char chpass[MAX_CHPASS_LEN];

  // make sure to unload previous chpasslist before loading again
  if (chpasslist_head) chpasslist_unload();

  if ((fp = std::fopen(chpassfile,"r"))==NULL)
  {
    eventlog(eventlog_level_error, __FUNCTION__,"can't open chpass file");
    return -1;
  }

  chpasslist_head = list_create();

  eventlog(eventlog_level_trace,__FUNCTION__,"start reading chpass file");

  while (std::fscanf(fp,"\"%[^\"]\",\"%[^\"]\"\n",channel_name,chpass)==2)
  {
    chpasslist_add_chpass(channel_name,chpass,DO_SAVE_CHPASS);
    eventlog(eventlog_level_trace,__FUNCTION__,"channel: %s chpass: \"%s\"",channel_name,chpass);
  }

  eventlog(eventlog_level_trace,__FUNCTION__,"finished reading chpass file");

  std::fclose(fp);
  return 0;
}

int chpasslist_unload(void)
{
  t_elem  * curr;
  t_chpass * chpass;

  if (chpasslist_head)
  {
    LIST_TRAVERSE(chpasslist_head,curr)
    {
      if (!(chpass = (t_chpass*)elem_get_data(curr)))
      {
        eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list");
        continue;
      }

      if (chpass->channel_name) xfree((void *)chpass->channel_name);
      if (chpass->chpass) xfree((void *)chpass->chpass);
      xfree((void *)chpass);
      list_remove_elem(chpasslist_head,&curr);
    }
    if (list_destroy(chpasslist_head)<0)
      return -1;

    chpasslist_head = NULL;
  }
  return 0;
}

}

}
